#ifndef __CoordinationRoleSequence_h__
#define __CoordinationRoleSequence_h__

#pragma once


#include "CoordinationElement.h"
#include "CoordinationTask.h"


class CoordinationRoleSequence
{
	struct RunningSequence;
	struct ActorState;
public:
	virtual ~CoordinationRoleSequence(){}
	CoordinationRoleSequence(const CoordinationSetup* setup, const CoordinationTaskMonitor* taskMonitor);

	void Reset();

	bool LoadFromXML(uint32 sequenceID, int roleID, const XmlNodeRef& rootNode);
	int GetRoleID() const;

	void DebugDrawStatus(const CoordinationID& coordinationID, CoordinationDebugDrawContext& context) const;

	ECoordinationState GetTaskState(const CoordinationID& coordinationID, int taskID) const;
	int GetCurrentTask(const CoordinationID& coordinationID) const;
	int GetCurrentTask(const CoordinationID& coordinationID, const CoordinationActor& actor) const;
	const char* GetTaskName(int taskID) const;

	virtual ECoordinationState GetState(const CoordinationID& coordinationID) const;
	virtual bool CanStart(const CoordinationInternalStartParams& params, const CoordinationActors& assignees) const;
	virtual void Start(const CoordinationID& coordinationID, const CoordinationActors& assignees);
	virtual void Stop(const CoordinationID& coordinationID);
	virtual void Stop(const CoordinationID& coordinationID, const CoordinationActor& targetActor);
	virtual void Update(float frameTime);
	virtual void Serialize(TSerialize ser);

	void UpdateEndSyncMode(const CoordinationID& coordinationID, RunningSequence& running);
	void UpdateTaskSyncMode(const CoordinationID& coordinationID, RunningSequence& running);

	void UpdateActor(const CoordinationID& coordinationID, RunningSequence& running, const CoordinationActor& actor, 
		ActorState& state);

private:
	enum ESyncMode
	{
		End = 0,
		Task,
	};

	typedef struct ActorState
	{
		ActorState():taskID(-1), state(CoordinationNotRunning), inBehavior(false){}
		int taskID;
		ECoordinationState state;
		bool inBehavior;

		void Serialize(TSerialize ser)
		{
			ser.Value("taskID", taskID);
			ser.EnumValue("state", state, CoordinationNotRunning, CoordinationFinished);
		}
	};
	typedef std::map<CoordinationActor, ActorState> ActorStates;

	typedef struct RunningSequence : public IActorBehaviorListener
	{
		RunningSequence()
			: state(CoordinationRunning), timeRun(0.0f), tasksStarted(false)
		{
		}

		~RunningSequence();

		ActorStates actors;
		ECoordinationState state;
		int taskID;
		float timeRun;
		bool tasksStarted;

		// IActorBehaviorListener
		virtual void BehaviorEvent(IAIObject* actor, EBehaviorEvent event);
		virtual void BehaviorChanged(IAIObject* actor, const char* current, const char* previous){};

		void Serialize(TSerialize ser)
		{
			ser.Value("actors", actors);
			ser.EnumValue("state", state, CoordinationNotRunning, CoordinationFinished);
			ser.Value("taskID", taskID);
			ser.Value("timeRun", timeRun);
			ser.Value("tasksStarted", tasksStarted);
		}
	};

	typedef std::map<CoordinationID, RunningSequence> RunningSequences;
	RunningSequences m_running;

	CoordinationTasks m_tasks;

	ESyncMode m_syncMode;
	int m_roleID;
	const CoordinationSetup* m_setup;
	const CoordinationTaskMonitor* m_taskMonitor;

	string m_signalName;

	CoordinationActors m_assignmentBuf;
};


class RoleSequences :
	public std::vector<CoordinationRoleSequence>
{
};


#endif //__CoordinationRoleSequence_h__